package io.kwdb.examples;

import io.kwdb.sdk.*;
import java.util.logging.*;

/**
 * Example 04: Security and TLS Configuration
 *
 * <p>Demonstrates: - TLS/SSL encrypted connections - Authentication methods (Bearer token, Basic
 * auth) - Custom CA certificate configuration - Gzip compression for bandwidth optimization -
 * Secure connection testing
 */
public class Example04_SecurityAndTLS {

  private static final Logger logger = Logger.getLogger(Example04_SecurityAndTLS.class.getName());

  public static void main(String[] args) throws Exception {
    System.out.println("====================================");
    System.out.println(" KWDB Java SDK M3 - Security Example");
    System.out.println("====================================\n");

    // Configure logging
    Logger.getLogger("io.kwdb").setLevel(Level.INFO);

    // Test 1: Bearer Token Authentication
    testBearerAuth();

    // Test 2: Basic Authentication
    testBasicAuth();

    // Test 3: TLS with Custom CA Certificate
    testTlsWithCaCert();

    // Test 4: Gzip Compression
    testGzipCompression();

    // Test 5: Combined Security Features
    testCombinedSecurity();

    System.out.println("\n====================================");
    System.out.println(" All Security Tests Completed");
    System.out.println("====================================");
  }

  /** Test Bearer token authentication. */
  private static void testBearerAuth() throws Exception {
    System.out.println("\n--- Test 1: Bearer Token Authentication ---");

    Config config =
        Config.builder()
            .host("127.0.0.1")
            .httpPort(9091)
            .transport(Config.Transport.ILP)
            .authToken("your-secure-token-here")
            .build();

    try (KwdbClient client = KwdbClient.create(config)) {
      System.out.println("Created client with Bearer token authentication");

      // Write a test point
      Point point =
          Point.builder("security_test")
              .tag("auth_type", "bearer")
              .field("test", "auth_success")
              .timestampNow()
              .build();

      Status status = client.write(point);
      if (status.isOk()) {
        System.out.println("✓ Successfully wrote point with Bearer auth");
      } else {
        System.out.println("✗ Write failed: " + status.getMessage());
        System.out.println("  (This is expected if server doesn't require auth)");
      }
    }
  }

  /** Test Basic authentication. */
  private static void testBasicAuth() throws Exception {
    System.out.println("\n--- Test 2: Basic Authentication ---");

    Config config =
        Config.builder()
            .host("127.0.0.1")
            .httpPort(9091)
            .transport(Config.Transport.ILP)
            .username("admin")
            .password("secure-password")
            .build();

    try (KwdbClient client = KwdbClient.create(config)) {
      System.out.println("Created client with Basic authentication");

      // Write a test point
      Point point =
          Point.builder("security_test")
              .tag("auth_type", "basic")
              .field("test", "auth_success")
              .timestampNow()
              .build();

      Status status = client.write(point);
      if (status.isOk()) {
        System.out.println("✓ Successfully wrote point with Basic auth");
      } else {
        System.out.println("✗ Write failed: " + status.getMessage());
        System.out.println("  (This is expected if server doesn't require auth)");
      }
    }
  }

  /** Test TLS connection with custom CA certificate. */
  private static void testTlsWithCaCert() throws Exception {
    System.out.println("\n--- Test 3: TLS with Custom CA Certificate ---");

    // Note: This requires a real CA certificate file
    // For testing, you would generate certificates using OpenSSL:
    // openssl req -new -x509 -days 365 -nodes -out ca.pem -keyout ca-key.pem

    Config config =
        Config.builder()
            .host("127.0.0.1")
            .httpPort(9091) // HTTPS port
            .transport(Config.Transport.ILP)
            .tls(true)
            .caCertPath("/path/to/ca.pem") // Custom CA certificate
            .build();

    try (KwdbClient client = KwdbClient.create(config)) {
      System.out.println("Created client with TLS and custom CA");
      System.out.println("Note: This test requires server to be configured with TLS");

      // Write a test point
      Point point =
          Point.builder("security_test")
              .tag("connection", "tls")
              .field("encrypted", true)
              .timestampNow()
              .build();

      Status status = client.write(point);
      if (status.isOk()) {
        System.out.println("✓ Successfully wrote point over TLS");
      } else {
        System.out.println("✗ Write failed: " + status.getMessage());
        System.out.println("  (Expected if server is not configured for TLS)");
      }
    } catch (Exception e) {
      System.out.println("✗ TLS connection failed (expected if server is not TLS-enabled)");
      System.out.println("  Error: " + e.getMessage());
    }
  }

  /** Test gzip compression for bandwidth optimization. */
  private static void testGzipCompression() throws Exception {
    System.out.println("\n--- Test 4: Gzip Compression ---");

    Config config =
        Config.builder()
            .host("127.0.0.1")
            .httpPort(9091)
            .transport(Config.Transport.ILP)
            .gzip(true) // Enable gzip compression
            .maxBatchSize(100) // Batch for better compression
            .lingerMs(100)
            .build();

    try (KwdbClient client = KwdbClient.create(config)) {
      System.out.println("Created client with gzip compression enabled");

      // Write many points to benefit from compression
      long startTime = System.currentTimeMillis();
      int numPoints = 100;

      for (int i = 0; i < numPoints; i++) {
        Point point =
            Point.builder("compression_test")
                .tag("host", "server-" + (i % 10))
                .tag("region", "us-west")
                .field("cpu_usage", Math.random() * 100)
                .field("memory_usage", Math.random() * 100)
                .field("disk_usage", Math.random() * 100)
                .field("network_in", Math.random() * 1000)
                .field("network_out", Math.random() * 1000)
                .timestampNow()
                .build();

        Status status = client.write(point);
        if (!status.isOk()) {
          System.err.println("Write failed: " + status.getMessage());
        }
      }

      // Flush to ensure all points are sent
      client.flush();

      long elapsed = System.currentTimeMillis() - startTime;
      System.out.println("✓ Wrote " + numPoints + " points with gzip in " + elapsed + "ms");
      System.out.println("  Compression reduces bandwidth usage significantly");
    }
  }

  /** Test combined security features. */
  private static void testCombinedSecurity() throws Exception {
    System.out.println("\n--- Test 5: Combined Security Features ---");

    // Combine multiple security features
    Config config =
        Config.builder()
            .host("127.0.0.1")
            .httpPort(9091)
            .transport(Config.Transport.ILP)
            // Security
            .tls(true)
            .authToken("secure-token")
            .gzip(true)
            // Performance
            .maxBatchSize(50)
            .lingerMs(100)
            .maxQueueSize(500)
            // Resilience
            .enableRetry(true)
            .maxRetries(3)
            .timeoutMillis(5000)
            .build();

    try (KwdbClient client = KwdbClient.create(config)) {
      System.out.println("Created client with full security configuration:");
      System.out.println("  - TLS encryption: enabled");
      System.out.println("  - Authentication: Bearer token");
      System.out.println("  - Compression: gzip");
      System.out.println("  - Batching: 50 points");
      System.out.println("  - Retry: 3 attempts");

      // Write test data
      for (int i = 0; i < 10; i++) {
        Point point =
            Point.builder("secure_data")
                .tag("security_level", "maximum")
                .field("sensitive_value", i * 3.14)
                .field("encrypted", true)
                .timestampNow()
                .build();

        Status status = client.write(point);
        if (!status.isOk()) {
          System.err.println("Write failed: " + status.getMessage());
        }
      }

      client.flush();
      System.out.println("✓ Successfully demonstrated combined security features");
      System.out.println("  (Some features may fail if server is not configured)");

    } catch (Exception e) {
      System.out.println("✗ Combined security test failed (expected without proper server config)");
      System.out.println("  Error: " + e.getMessage());
    }
  }

  /** Helper method to demonstrate secure connection verification. */
  private static void verifySecureConnection(Config config) {
    System.out.println("\n--- Verifying Secure Connection ---");

    if (config.isTls()) {
      System.out.println("✓ TLS/SSL: ENABLED");
      if (config.getCaCertPath() != null) {
        System.out.println("✓ Custom CA: " + config.getCaCertPath());
      } else {
        System.out.println("✓ Using system trust store");
      }
    } else {
      System.out.println("⚠ TLS/SSL: DISABLED (connection not encrypted)");
    }

    if (config.getAuthToken() != null) {
      System.out.println("✓ Authentication: Bearer Token");
    } else if (config.getUsername() != null) {
      System.out.println("✓ Authentication: Basic (user: " + config.getUsername() + ")");
    } else {
      System.out.println("⚠ Authentication: NONE");
    }

    if (config.isGzip()) {
      System.out.println("✓ Compression: GZIP enabled");
    } else {
      System.out.println("⚠ Compression: DISABLED");
    }
  }
}
